// bot1.v - Reference design for ECE 540 Rojobot Getting Started project
//
// Copyright John Lynch and Roy Kravitz, 2006-2013, 2014
// 
// Created By:		John Lynch
// Last Modified:	31-Dec-2014 (RK)
//
// Revision History:
// -----------------
// Dec-2006		JL		Created this module for ECE 540
// Dec-2014		RK		Cleaned up the formatting.  No functional changes
//
// Description:
// ------------
// This module is the reference design for the ECE 540 Getting Started project.  It
// emulates a simple two-wheeled robot.  Each wheel is controlled independently by
// pushbuttons.  The "forward" buttons increase 8-bit wheel counters (one per wheel)
// The "reverse" buttons decrease the wheel counters.  The wheel counters are 
// incremented at 5Hz by dividing the 100MHz Nexys 3 system clock down to 5Hz.
// The "simulate" parameter should be set to 1'b1 if the design is being
// simulated to keep the simulation time reasonable
// 
///////////////////////////////////////////////////////////////////////////
`timescale  1 ns / 1 ns
module RojoBot1(
    input clk, reset, left_fwd, left_rev, right_fwd, right_rev,
    output reg [4:0] left_pos = 5'd16, 
	 output reg [14:0] right_pos = 15'd0
    );
    
    parameter  simulate = 0;
    localparam rojobot_cnt = simulate ? 26'd5			// rojobot clock when simulating
                                      : 26'd99_999_999; // rojobot count when running on HW (5Hz)

	//internal registers	
	reg [25:0]	ck_count=0,ck_count1 = 0,ck_count2=0;	//clock divider counter
	reg 		tick1hz, tick5hz,tick10hz;		// 5 Hz clock enable
	
	// generate 1Hz clock enable
	always @(posedge clk)
		if (ck_count == rojobot_cnt) begin
		    tick1hz <= 1'b1;
		    ck_count <= 0;
		end
		else begin
		    ck_count <= ck_count + 1'b1;
		    tick1hz <= 0;
      end
		
		// generate 5Hz clock enable
		always @(posedge clk)
		if (ck_count1 == 26'd1_999_999) begin
		    tick50hz <= 1'b1;
		    ck_count1 <= 0;
		end
		else begin
		    ck_count1 <= ck_count1 + 1'b1;
		    tick50hz <= 0;
      end
    

	 	// generate 10Hz clock enable
		always @(posedge clk)
		if (ck_count2 == 26'd9_999_999) begin
		    tick20hz <= 1'b1;
		    ck_count2 <= 0;
		end
		else begin
		    ck_count2 <= ck_count2 + 1'b1;
		    tick20hz <= 0;
      end
    // motion indicator & compass operations    
	always @(posedge clk or posedge reset) begin
		
		
		// segment g steady 'on' on system clock 
		case ({left_fwd, left_rev,right_fwd, right_rev})
		4'b0000,4'b1111,4'b1100,4'b0011: begin 
										left_pos <= 5'd22;
										
									     end
									
		endcase
		
		if (reset) begin
			left_pos <= 5'd16;     // initialize  left digit to seg a
			right_pos <= 15'd0;    // initialize  right 3 digits to 0
	end 
		else if(tick1hz) begin
				case ({left_fwd, left_rev,right_fwd, right_rev})
					4'b1010: begin 
										left_pos <= (left_pos == 5'd16)?(5'd30):(5'd16);      // segment a blinks 
								
							end
									
					4'b0101: begin 
										left_pos <= (left_pos == 5'd19)?(5'd30):(5'd19);     // segment d blinks 
								
							end
					
					
				endcase
			end
			else
			if(tick5hz) begin
				case ({left_fwd, left_rev,right_fwd, right_rev})
					4'b1000 ,4'b0001:	begin 
										// clockwise chase  1X
										left_pos <= (left_pos == 5'd22)?(5'd16):((left_pos == 5'd21)? (5'd16) : (left_pos + 1'b1)); 
										
										// clockwise compass 1x speed 										
										right_pos[4:0] <= (right_pos[4:0]==9) ? 0 : right_pos[4:0]+1 ;

                                        right_pos[9:5] <= (right_pos[4:0]==9) ? ((right_pos[14:10]==3)?((right_pos[9:5]==5)?(0):(right_pos[9:5]+1)):((right_pos[9:5]==9)?(0):(right_pos[9:5]+1))) : right_pos[9:5];

                                        right_pos[14:10] <= right_pos[14:10] <= (right_pos[14:10]==3) ? ((right_pos[9:5]==5)?((right_pos[4:0]==9)?(0):(right_pos[14:10])):(right_pos[14:10])) : ((right_pos[9:5]==9)?((right_pos[4:0] == 9) ? (right_pos[14:10] +1) : (right_pos[14:10])):(right_pos[14:10]));

									    end
									
									
				
					4'b0010,4'b0100: begin 
					                      // anti-clockwise chase 1X
										  left_pos <= (left_pos == 5'd22)?(5'd16):((left_pos == 5'd16)? (5'd21) : (left_pos - 1'b1)); 
										
									      // anticlockwise compass 1x speed 
                                          right_pos[4:0] <= (right_pos[4:0]==0) ? (9) : (right_pos[4:0]-1);

                                          right_pos[9:5] <= (right_pos[4:0]==0)?((right_pos[14:10]==0)?((right_pos[9:5]==0)?(5):(right_pos[9:5]-1)):((right_pos[9:5]==0)?(9):(right_pos[9:5]-1))) : right_pos[9:5];

                                          right_pos[14:10] <= (right_pos[14:10]==0) ? ((right_pos[9:5]==0)?((right_pos[4:0]==0)?(3):(right_pos[14:10])):(right_pos[14:10])) : ((right_pos[9:5] == 0) ? (( right_pos[4:0] == 0 ) ? ( right_pos[14:10] - 1 ) : ( right_pos[14:10] ) ) : ( right_pos[14:10] )) ;
									end
		
									
				endcase
			end
		else begin
			if(tick50hz) begin
				case ({left_fwd, left_rev,right_fwd, right_rev})
					4'b1001:	begin 
					                      // clockwise chase 2X
									      left_pos <= (left_pos == 5'd22)?(5'd16):((left_pos == 5'd21)? (5'd16) : (left_pos + 1'b1)); 
									  
									      // clockwise compass 2x speed 
									      right_pos[4:0] <= (right_pos[4:0]==9) ? 0 : right_pos[4:0]+1;


                                          right_pos[9:5] <= (right_pos[4:0]==9) ? ((right_pos[14:10]==3)?((right_pos[9:5]==5)?(0):(right_pos[9:5]+1)):((right_pos[9:5]==9)?(0):(right_pos[9:5]+1))) : right_pos[9:5];

                                          right_pos[14:10] <= (right_pos[14:10]==3) ? ((right_pos[9:5]==5)?((right_pos[4:0]==9)?(0):(right_pos[14:10])):(right_pos[14:10])) : ((right_pos[9:5]==9)?((right_pos[4:0] == 9) ? (right_pos[14:10] +1) : (right_pos[14:10])):(right_pos[14:10]));



                                end
				
					4'b0110: begin 
					                      // anti-clockwise chase 2X
										  left_pos <= (left_pos == 5'd22)?(5'd16):((left_pos == 5'd16)? (5'd21) : (left_pos - 1'b1)); 
										
									      // anticlockwise compass 2x speed 
                                          right_pos[4:0] <= (right_pos[4:0]==0) ? (9) : (right_pos[4:0]-1);

                                          right_pos[9:5] <= (right_pos[4:0]==0)?((right_pos[14:10]==0)?((right_pos[9:5]==0)?(5):(right_pos[9:5]-1)):((right_pos[9:5]==0)?(9):(right_pos[9:5]-1))) : right_pos[9:5];

                                          right_pos[14:10] <= (right_pos[14:10]==0) ? ((right_pos[9:5]==0)?((right_pos[4:0]==0)?(3):(right_pos[14:10])):(right_pos[14:10])) : ((right_pos[9:5] == 0) ? (( right_pos[4:0] == 0 ) ? ( right_pos[14:10] - 1 ) : ( right_pos[14:10] ) ) : ( right_pos[14:10] )) ;


 							end
						
				endcase
			end
		end
		
	end
    
endmodule
